import EventUtil from "./event/EventUtil";
import { Events } from "./event/Event";
import QuadTree from "./QuadTree";
import AABB from "./AABB";
import QuadTreeNode from "./QuadTreeNode";
import Misc from "./Misc";
const { ccclass, property } = cc._decorator;

@ccclass
export default class Scene extends cc.Component {

  @property(cc.Prefab)
  private pfbAABB: cc.Prefab = null;

  @property(cc.Node)
  private nodConer: cc.Node = null;

  @property(cc.Graphics)
  private graphicsRect: cc.Graphics = null;

  @property(cc.Node)
  private nodDrag: cc.Node = null;

  @property(cc.Label)
  private labTotal: cc.Label = null;

  // 四叉树
  private quadTree: QuadTree = null;

  // 当前碰撞对象
  private mArrCollision: AABB[] = [];

  // 当前所有对象
  private mArrAllAABB: AABB[] = [];

  protected onLoad() {
    EventUtil.Dispatcher.on(Events.EVENT_DRAW_RECT, this.onDrawRect, this);
    EventUtil.Dispatcher.on(Events.EVENT_RESET_AABB_PATH, this.onRestPath, this);

    const w = 1280;
    const h = 720;
    this.quadTree = new QuadTree(cc.rect(-w / 2, -h / 2, w, h));

    this.node.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);

  }

  private onDrawRect(params: any) {
    const rect = params.rect;
    const depth = params.depth;

    if (depth === 0) {
      this.graphicsRect.strokeColor = cc.Color.RED;
    } else if (depth === 1) {
      this.graphicsRect.strokeColor = cc.Color.GREEN;
    } else if (depth === 2) {
      this.graphicsRect.strokeColor = cc.Color.BLUE;
    } else {
      this.graphicsRect.strokeColor = cc.Color.RED;
    }

    this.graphicsRect.rect(rect.x, rect.y, rect.width, rect.height);
    this.graphicsRect.stroke();
  }

  protected update(dt) {

    // 性能测试
    // console.time("move Time");
    for (let i = 0; i < this.mArrAllAABB.length; i++) {
      this.mArrAllAABB[i].onUpdate(dt);
    }
    // console.timeEnd("move Time");

    const rect = this.nodDrag.getBoundingBox();
    for (let i = 0; i < this.mArrCollision.length; i++) {
      this.mArrCollision[i].node.color = cc.Color.WHITE;
    }

    this.mArrCollision = this.quadTree.retrieve(rect);

    for (let i = 0; i < this.mArrCollision.length; i++) {
      if (this.mArrCollision[i].node.getBoundingBox().intersects(rect)) {
        this.mArrCollision[i].node.color = cc.Color.RED;
      }
    }
  }

  // 插入节点
  public insert(pObject: AABB, isNew: boolean = true) {
    if (isNew && this.mArrAllAABB.indexOf(pObject) === -1) {
      this.mArrAllAABB.push(pObject);
      this.labTotal.string = "总数：" + this.mArrAllAABB.length;
    }
    this.quadTree.insert(pObject);
  }

  // 重置路径
  public onRestPath(pObject: AABB) {
    this.insert(pObject, false);
  }

  // 增加1个
  private onBtnAdd1() {
    const nod = cc.instantiate(this.pfbAABB);
    nod.parent = this.nodConer;
    this.insert(AABB.GetComponent(nod));
  }

  // 增加10个
  private onBtnAdd10() {
    for (let i = 0; i < 100; i++) {
      const nod = cc.instantiate(this.pfbAABB);
      nod.parent = this.nodConer;
      this.insert(AABB.GetComponent(nod));
    }
  }

  // 单个删除
  private onBtnDel1() {
    const random = Misc.getRandomInt(0, this.mArrAllAABB.length - 1);
    const object = this.mArrAllAABB[random];
    if (object) {
      console.log("删除节点 --- ", object.mNumIndex);
      this.mArrAllAABB.splice(random, 1);
      EventUtil.Dispatcher.emit(Events.EVENT_DELETE_AABB + object.mNumIndex);
    }
  }

  // 树的信息
  private onBtnInfo() {
    const debug = (node: QuadTreeNode) => {
      const result = [];
      for (let i = 0; i < node.mArrObject.length; i++) {
        result.push(node.mArrObject[i].mNumIndex);
      }
      console.log(node.mStrDepthPath, result);

      for (let i = 0; i < node.mArrLeafNode.length; i++) {
        debug(node.mArrLeafNode[i]);
      }
    };
    debug(this.quadTree.mNodRoot);
  }

  // 性能测试
  private onBtnPerformance() {
    const rect = this.nodDrag.getBoundingBox();

    console.time("Quad Time");
    this.mArrCollision = this.quadTree.retrieve(rect);
    for (let i = 0; i < this.mArrCollision.length; i++) {
      if (this.mArrCollision[i].node.getBoundingBox().intersects(rect)) {
        this.mArrCollision[i].node.color = cc.Color.RED;
      }
    }
    console.timeEnd("Quad Time");


    console.time("foreach Time");
    for (let i = 0; i < this.mArrAllAABB.length; i++) {
      if (this.mArrAllAABB[i].node.getBoundingBox().intersects(rect)) {
        this.mArrAllAABB[i].node.color = cc.Color.RED;
      }
    }
    console.timeEnd("foreach Time");
  }

  private onTouchMove(event: cc.Touch) {
    this.nodDrag.position = this.node.convertToNodeSpaceAR(event.getLocation());
  }
}
